package com.yeskery.nut.util;

import com.yeskery.nut.core.Controller;
import com.yeskery.nut.core.DynamicControllerAdapter;
import com.yeskery.nut.core.Request;
import com.yeskery.nut.scan.controller.AnnotationControllerInvocationHandler;
import com.yeskery.nut.scan.controller.AnnotationRequestMethodAttributes;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * Controller工具类
 * @author sprout
 * @version 1.0
 * 2023-07-22 20:16
 */
public class ControllerUtils {

    /**
     * 私有化构造方法
     */
    private ControllerUtils() {
    }

    /**
     * 获取注解式Controller当前请求的执行方法
     * @param controller Controller对象
     * @param request 当前请求对象
     * @return 执行方法
     */
    public static Method getAnnotationControllerExecuteMethod(Controller controller, Request request) {
        if (controller instanceof DynamicControllerAdapter) {
            controller = ((DynamicControllerAdapter) controller).getController();
        }
        if (!(controller instanceof Proxy)) {
            return null;
        }
        InvocationHandler invocationHandler = Proxy.getInvocationHandler(controller);
        if (!(invocationHandler instanceof AnnotationControllerInvocationHandler)) {
            return null;
        }
        Map<com.yeskery.nut.core.Method, AnnotationRequestMethodAttributes> methodHandleMap =
                ((AnnotationControllerInvocationHandler) invocationHandler).getAnnotationMethodHandleMap();
        AnnotationRequestMethodAttributes attributes = methodHandleMap.get(request.getMethod());
        if (attributes == null) {
            attributes = methodHandleMap.get(com.yeskery.nut.core.Method.ALL);
        }
        return attributes == null ? null : attributes.getMethod();
    }

    /**
     * 获取注解式Controller当前请求的执行方法上的注解
     * @param controller Controller对象
     * @param request 当前请求对象
     * @param annotationClass 注解的类型
     * @param <T> 注解类型
     * @return 执行方法上的注解
     */
    public static <T extends Annotation> T getAnnotationControllerMethodAnnotation(Controller controller, Request request,
                                                                                   Class<T> annotationClass) {
        return getAnnotationControllerMethodAnnotation(getAnnotationControllerExecuteMethod(controller, request), annotationClass);
    }

    /**
     * 获取注解式Controller当前请求的执行方法或类上的注解
     * @param controller Controller对象
     * @param request 当前请求对象
     * @param annotationClass 注解的类型
     * @param <T> 注解类型
     * @return 执行方法或类上的注解
     */
    public static <T extends Annotation> T getAnnotationControllerMethodOrClassAnnotation(Controller controller, Request request,
                                                                                   Class<T> annotationClass) {
        return getAnnotationControllerMethodOrClassAnnotation(getAnnotationControllerExecuteMethod(controller, request), annotationClass);
    }

    /**
     * 获取注解式Controller当前请求的执行方法上的注解
     * @param method 执行方法
     * @param annotationClass 注解的类型
     * @param <T> 注解类型
     * @return 执行方法上的注解
     */
    public static <T extends Annotation> T getAnnotationControllerMethodAnnotation(Method method, Class<T> annotationClass) {
        return method == null ? null : method.getAnnotation(annotationClass);
    }

    /**
     * 获取注解式Controller当前请求的执行方法或类上的注解
     * @param method 执行方法
     * @param annotationClass 注解的类型
     * @param <T> 注解类型
     * @return 执行方法或类上的注解
     */
    public static <T extends Annotation> T getAnnotationControllerMethodOrClassAnnotation(Method method, Class<T> annotationClass) {
        if (method == null) {
            return null;
        }
        T annotation = method.getAnnotation(annotationClass);
        return annotation == null ? method.getDeclaringClass().getAnnotation(annotationClass) : annotation;
    }
}
